#include "task.hpp"
#define N 5
#define BUFFSIZE 1024
extern int errno;
int pipefd[2] = {0};
char buff[BUFFSIZE];

//对子进程封装
class channel{
public:
    int wfd;//读端口
    int pid;//子进程pid
    string name; 
public:
    channel() = default;
    channel(int _wfd,int _pid,string& _name)
    :wfd(_wfd),pid(_pid),name(_name)
    {}
};

//子进程接收信息
void receive_task(){
    while(true){
        int n = read(0,buff,BUFFSIZE);
        buff[n] = 0;
        if(n==0) break;//父进程关闭了写端
        cout<<"i am child,pid: " << getpid() << " ";
        int pos = buff[0] - '0';
        taskobj.executeTask(pos-1);
        cout<<endl;
    }
    close(0);
}

// //子进程选择器
// int choose_process(){
//     srand(time(nullptr)^0xf327ff+0x2f37);
//     return rand()%N;
// }

void menu(){
    cout<<"######################################"<<endl;
    cout<<"####  1.刷新屏幕     2.创建游戏界面 ####"<<endl;
    cout<<"######################################"<<endl;
    cout<<"####  3.刷新技能     4.检测更新  #######"<<endl;
    cout<<"###########    0.退出     ############"<<endl;
    cout<<"#####################################"<<endl;
}

//父进程发放信息
void Assign_task(const vector<channel>& channels){
    //int cnt = 5;
    int pos = 0;//子进程轮询选择
    while(true){
        menu();
        cout<<"Please Enter@:";
        string msg; getline(cin,msg);
        if(msg=="0") break;
        // cout<<"father say@ pid = "<< channels[pos].pid 
        //     << ", name=" <<  channels[pos].name 
        //     << ",execute:"<<msg<<endl;
        int n = write(channels[pos].wfd,msg.c_str(),msg.size());
        pos = (pos+1)%N;
        sleep(1);
    }
}


//创建一批子进程并创建匿名管道
void InitProcess(vector<channel>* channels){
    vector<int> prewritefd;//记录父进程有那些写端,防止子进程指向父进程的写端
    for(int i=0;i<N;++i){
        if(-1 == pipe(pipefd)){
            perror("pipe");
            exit(errno);
        }
        int id = fork();
        if(-1 == id){
            perror("fork");
            exit(errno);
        }else if(0 == id){//子进程
            for(auto& fd : prewritefd) close(fd);//关闭继承下来的写端
            close(pipefd[1]);
            dup2(pipefd[0],0);//把stdin流重定向到管道读端口
            close(pipefd[0]);
            receive_task();
            exit(0);
        }
        close(pipefd[0]);
        prewritefd.push_back(pipefd[1]);
        (*channels)[i].wfd = pipefd[1],(*channels)[i].pid = id;
        (*channels)[i].name = "process: " + to_string(id) + ", pos-" + to_string(i);
    }
}

//释放子进程,并清理管道
void ClearProcess(vector<channel>& channels){
    for(int i=0;i<N;++i){
        close(channels[i].wfd);
        int retid = waitpid(channels[i].pid,NULL,0);
        if(retid<0){
            perror("waitpid");
            exit(errno);
        }
        if(retid > 0){
            cout<<"succesful wait process: " << retid << endl;
        }
    }
}

int main(){
    vector<channel> channels(N);
    InitProcess(&channels);
    Assign_task(channels);
    ClearProcess(channels);
    return 0;
}